package net.chathu.airgw 
{
	import flash.events.TimerEvent;
	import flash.system.System;
	import flash.utils.Timer;
	import net.chathu.airgw.event.DataSendEvent;
	import net.chathu.airgw.model.AccountData;
	import net.chathu.airgw.model.ChatData;
	import net.chathu.airgw.model.conn.ChatServerConnection;
	import net.chathu.airgw.model.conn.DecryptedChatServerConnection;
	import net.chathu.airgw.model.conn.GWConnection;
	import net.chathu.airgw.model.conn.IChatServerConnection;
	import net.chathu.airgw.model.conn.IRCConnection;
	import net.chathu.airgw.model.conn.P2PChatConnection;
	import net.chathu.airgw.model.SessionData;
	import net.chathu.airgw.packets.gw.serverpackets.EchoPacket;
	import net.chathu.airgw.packets.gw.serverpackets.NoticePacket;
	import net.chathu.airgw.packets.redirect.LoginErrorPacket;
	import net.chathu.airgw.packets.redirect.LoginFailPacket;
	import net.chathu.airgw.packets.redirect.LoginOKPacket;
	import net.chathu.airgw.util.ByteArrayUtil;
	import net.chathu.airgw.util.LoginHelper;

	
	
	

	/**
	 * ...
	 * @author ze
	 */
	public class Soul 
	{
		//Nemhogy jobb nem jut eszembe, csak rosszabbak.. 
		//Ha lesz jobb, atnevezem ...
		
		private var actAsGW:Boolean = true; //ha nem kapcsolodunk masik gwre, tehat mi vesszuk at ezt a feladatot
		private var _gwConnection:GWConnection; //ez lehet null
		
		private var _ircConnection:IRCConnection;
		private var _chatServerConnection:IChatServerConnection;
		private var _p2pChatConnection:P2PChatConnection;
		private var _accountData:AccountData; //ez is mehet sessionData-ba
		private var _sessionData:SessionData;
		
		private var loginInfo:LoginHelper;
		
		private static var ID_COUNTER:int=0;
		private var _id:int;
		
		public function Soul() 
		{
			_id = ID_COUNTER++;
			_sessionData = new SessionData(this);
			_accountData = new AccountData();
		}
		
		public function get gwConnection():GWConnection
		{
			return _gwConnection;
		}
		
		public function get ircConnection():IRCConnection
		{
			return _ircConnection;
		}
		
		public function set ircConnection(conn:IRCConnection):void
		{
			if (_ircConnection)
			{
				throw new Error("IRCConnection is already set");
			} else {
				_ircConnection = conn;
			}
		}
		
		public function set p2pChatConnection(conn:P2PChatConnection):void
		{
			if (_p2pChatConnection)
			{
				throw new Error("P2PChatConnection is already set");
			} else {
				_p2pChatConnection = conn;
			}
		}
		
		public function get p2pChatConnection():P2PChatConnection
		{
			return _p2pChatConnection;
		}
		
		public function get chatServerConnection():IChatServerConnection
		{
			return _chatServerConnection;
		}
		
		public function createGWConnection(host:String="localhost",port:int=7001):void
		{
			actAsGW = false;
			//TODO
			/*if (_gwConnection... es kapcsolodva is van..)
			{
				return;
			}*/
			if (_gwConnection) 
			{
				return;
			}
			_gwConnection = new GWConnection(this, host,port);
		}
		
		public function createChatConnection():void
		{
			/*if (_chatServerConnection... es kapcsolodva is van..)
			{
				return;
			}*/
			if (_chatServerConnection)
			{
				return;
			}
			if (!_sessionData.SID)
			{
				Debug.echo("Missing SID, chat connect disabled");
				return;
			}
			sessionData.chatData = new ChatData();
			//var host:String = "94.125.253.89";
			//var host:String = "94.125.253.41";
			//var ports:Array = [ 23, 53, 77, 110, 443, 4000];
			
			var port:int = Config.CHAT_SERVER_PORTS[Math.floor(Math.random() * Config.CHAT_SERVER_PORTS.length)];
			Debug.echo("Connecting to " + Config.CHAT_SERVER_HOST + ":" + port);
			if (actAsGW)
			{
				_chatServerConnection = new DecryptedChatServerConnection(this, Config.CHAT_SERVER_HOST, port);
			} else {
				_chatServerConnection = new ChatServerConnection(this, Config.CHAT_SERVER_HOST, port);
			}
		}
		
		public function webLogin():void {
			if (loginInfo)
			{
				loginInfo.removeEventListener(LoginHelper.SID_OK, onSidOK);
				loginInfo.removeEventListener(LoginHelper.SID_FAIL, onSidFail);
				loginInfo = null;
			}
			loginInfo = new LoginHelper();
			loginInfo.addEventListener(LoginHelper.SID_OK, onSidOK);
			loginInfo.addEventListener(LoginHelper.SID_FAIL, onSidFail);
			loginInfo.getSID(accountData.username,accountData.password);
		}
		
		
		private function onSidOK(event:DataSendEvent):void
		{
			if (loginInfo)
			{
				loginInfo.removeEventListener(LoginHelper.SID_OK, onSidOK);
				loginInfo.removeEventListener(LoginHelper.SID_FAIL, onSidFail);
				loginInfo = null;
			}
			_sessionData.SID = event.data;
			
			if (actAsGW)
			{
				//Ha masnak nincs dolga ezzel, mi dolgozzuk fel
				createChatConnection();
			} else {
				//Tovabbitjuk az esemenyt
				_gwConnection.sendRedirectorPacket(new LoginOKPacket(event.data, ""));
			}
		}
		
		private function onSidFail(event:DataSendEvent):void
		{
			if (loginInfo)
			{
				loginInfo.removeEventListener(LoginHelper.SID_OK, onSidOK);
				loginInfo.removeEventListener(LoginHelper.SID_FAIL, onSidFail);
				loginInfo = null;
			}
			_sessionData.SID = null;
			//noSid/loginFail/httpError
			Debug.echo(event.data);
			if (actAsGW)
			{
				if (_ircConnection)
				{
					
				} else {
					Debug.echo("Can't get SID! Test failed.");
				}
			} else {
				if (event.data == "loginFail")
				{
					_gwConnection.sendRedirectorPacket(new LoginFailPacket());
				} else {
					_gwConnection.sendRedirectorPacket(new LoginErrorPacket());
				}
			}
			//TODO: kesobb ide nem kell destroy!
			//destroy();
		}
		
		public function onChatDisconnected():void {
			//_ircConnection.sendPacket(new NoticePacket("test", sessionData.nick, "Chat disconnect!"));
			//webLogin();
			destroy();
		}
		
		public function get accountData():AccountData
		{
			return _accountData;
		}
		
		public function get sessionData():SessionData
		{
			return _sessionData;
		}
		
		public function get id():int
		{
			return _id;
		}
		
		public function destroy():void
		{
			trace("Soul destroy!"  + this._id);
			//1.
			//Close chat connection properly:
			if (_chatServerConnection && chatServerConnection.connected)
			{
				if (_chatServerConnection is DecryptedChatServerConnection) {
					DecryptedChatServerConnection(_chatServerConnection).close(true);
				}
			}
			_chatServerConnection = null;
			
			//2.
			//Close GW connection properly:
			//TODO:check this..+rename disconnect to close:
			if (_gwConnection) {
				_gwConnection.disconnect();
			}
			//_gwConnection = null;
			
			//3.
			//Close irc connection properly:
			
			if (_ircConnection && ircConnection.connected)
			{
				_ircConnection.sendPacket(new EchoPacket(Config.GW_ECHO_NICK, "Bye-bye!"));
				_ircConnection.close();
			}
			//_ircConnection = null;
			
			//if (_p2pChatConnection && _p2pChatConnection.connected)
			if (_p2pChatConnection)
			{
				_p2pChatConnection.close();
			}
			
			//3. destroy sessionData
			/*if (sessionData)
			{
				_sessionData.destroy();
				_sessionData = null;
			}*/
			//ez kell ide, ha nem a soulmanager hivta volna!
			SoulManager.removeSoul(this);
			
			//call GC twice!
			System.gc();
			System.gc();
		}
		
	}

}